#include "Application.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <csignal>
#include <cstring>
#include <fstream>

// 获取单例实例
Application& Application::getInstance() {
    static Application instance;
    return instance;
}

// 构造函数
Application::Application() : running(false) {
}

// 析构函数
Application::~Application() {
    stop();
}

// 初始化应用程序
bool Application::initialize() {
    try {
        // 初始化日志
        Logger& logger = Logger::getInstance();
        Config& config = Config::getInstance();
        
        // 设置日志级别
        logger.setLogLevel(INFO);
        
        LOG_INFO("GB28181客户端 - V5摄像头版本启动");
        LOG_INFO("使用硬编码配置");
        LOG_INFO("若需修改配置，请编辑源代码中的Config类");
        
        // 初始化SIP管理器
        SipManager& sipManager = SipManager::getInstance();
        
        // 设置SIP回调
        sipManager.setCallbacks(
            [this](pjsua_acc_id acc_id) { this->handleRegState(acc_id); },
            [this](pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) { this->handleIncomingCall(acc_id, call_id, rdata); },
            [this](pjsua_call_id call_id, pjsip_event *e) { this->handleCallState(call_id, e); },
            [this](pjsua_call_id call_id) { this->handleCallMediaState(call_id); },
            [this](pjsip_rx_data *rdata) { return this->handleRxRequest(rdata); }
        );
        
        // 初始化SIP
        if (!sipManager.initialize()) {
            LOG_ERROR("SIP初始化失败");
            return false;
        }
        
        // 注册SIP账户
        if (!sipManager.registerAccount()) {
            LOG_ERROR("SIP账户注册失败");
            return false;
        }
        
        // 测试SDP解析
        testSdpParsing();
        
        LOG_INFO("应用程序初始化成功");
        return true;
    } catch (const std::exception& e) {
        LOG_ERROR("应用程序初始化异常: " + std::string(e.what()));
        return false;
    }
}

// 运行应用程序
void Application::run() {
    if (running) {
        LOG_WARN("应用程序已经在运行中");
        return;
    }
    
    running = true;
    LOG_INFO("GB28181客户端运行中，等待平台的点播请求...");
    LOG_INFO("按Ctrl+C退出程序");
    
    // 主循环
    while (running) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

// 停止应用程序
void Application::stop() {
    if (!running) {
        return;
    }
    
    running = false;
    LOG_INFO("正在停止应用程序...");
    
    // 停止流媒体
    StreamManager::getInstance().stopStreaming();
    
    // 关闭SIP
    SipManager::getInstance().shutdown();
    
    LOG_INFO("应用程序已停止");
}

// 是否正在运行
bool Application::isRunning() const {
    return running;
}

// 处理SIP注册状态
void Application::handleRegState(pjsua_acc_id acc_id) {
    pjsua_acc_info info;
    pjsua_acc_get_info(acc_id, &info);
    
    if (info.status == 200 || info.status == 0) {
        LOG_INFO("SIP注册成功");
    } else {
        LOG_WARN("SIP注册失败或注销，状态码: " + std::to_string(info.status));
    }
}

// 处理SIP呼入请求
void Application::handleIncomingCall(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) {
    LOG_INFO("收到呼叫请求 ID: " + std::to_string(call_id) + " 账户ID: " + std::to_string(acc_id));
    
    try {
        // 检查是否有SDP
        if (!rdata) {
            LOG_ERROR("错误: INVITE请求数据为空");
            throw std::runtime_error("INVITE请求数据为空");
        }
        
        if (!rdata->msg_info.msg) {
            LOG_ERROR("错误: INVITE消息为空");
            throw std::runtime_error("INVITE消息为空");
        }
        
        if (!rdata->msg_info.msg->body) {
            LOG_ERROR("错误: INVITE请求中没有SDP正文");
            throw std::runtime_error("INVITE请求中没有SDP");
        }
        
        // 获取INVITE请求
        pjsip_msg* invite_msg = rdata->msg_info.msg;
        
        // 获取From和To头信息
        pjsip_from_hdr* from_hdr = (pjsip_from_hdr*)pjsip_msg_find_hdr(invite_msg, PJSIP_H_FROM, NULL);
        pjsip_to_hdr* to_hdr = (pjsip_to_hdr*)pjsip_msg_find_hdr(invite_msg, PJSIP_H_TO, NULL);
        
        if (from_hdr && from_hdr->uri) {
            char uri_str[PJSIP_MAX_URL_SIZE];
            int len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, from_hdr->uri, uri_str, sizeof(uri_str));
            if (len > 0) {
                LOG_INFO("呼叫来自: " + std::string(uri_str, len));
            }
        }
        
        if (to_hdr && to_hdr->uri) {
            char uri_str[PJSIP_MAX_URL_SIZE];
            int len = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, to_hdr->uri, uri_str, sizeof(uri_str));
            if (len > 0) {
                LOG_INFO("呼叫目标: " + std::string(uri_str, len));
            }
        }
        
        // 获取并解析SDP
        std::string sdp_offer((char*)invite_msg->body->data, invite_msg->body->len);
        LOG_INFO("收到SDP Offer: \n" + sdp_offer);
        
        // 解析SDP并设置推流参数
        StreamManager& streamManager = StreamManager::getInstance();
        if (!streamManager.parseSdpAndSetParams(sdp_offer)) {
            LOG_ERROR("解析SDP失败");
            throw std::runtime_error("解析SDP失败");
        }
        
        // 生成SDP应答
        std::string sdp_answer = streamManager.generateSdpAnswer();
        
        // 接受呼叫
        pjsua_msg_data msg_data;
        pjsua_msg_data_init(&msg_data);
        
        // 设置SDP类型和内容
        msg_data.content_type = pj_str((char*)"application/sdp");
        msg_data.msg_body = pj_str((char*)sdp_answer.c_str());
        
        // 发送200 OK应答
        LOG_INFO("正在接受呼叫...");
        pj_status_t status = pjsua_call_answer(call_id, 200, NULL, &msg_data);
        if (status != PJ_SUCCESS) {
            char errmsg[PJ_ERR_MSG_SIZE];
            pj_strerror(status, errmsg, sizeof(errmsg));
            std::string errstr = std::string(errmsg);
            LOG_ERROR("接受呼叫失败，错误码: " + std::to_string(status) + ", 错误信息: " + errstr);
            throw std::runtime_error(std::string("接受呼叫失败: ") + errstr);
        }
        
        LOG_INFO("成功接受呼叫，SDP应答已发送");
        
        // 等待确保SDP交换完成
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        
        // 启动推流
        LOG_INFO("准备启动推流...");
        if (!streamManager.startStreaming()) {
            LOG_ERROR("启动推流失败");
            throw std::runtime_error("启动推流失败");
        }
        
        LOG_INFO("推流已启动");
    } catch (const std::exception& e) {
        LOG_ERROR("处理呼入请求时出错: " + std::string(e.what()));
        
        // 尝试使用不同的拒绝方式
        try {
            LOG_INFO("尝试拒绝呼叫，响应码488...");
            pjsua_call_info ci;
            pj_status_t status = pjsua_call_get_info(call_id, &ci);
            if (status == PJ_SUCCESS) {
                // 如果可以获取呼叫信息，则使用pjsua_call_hangup
                pjsua_call_hangup(call_id, 488, NULL, NULL);
            } else {
                // 尝试直接回复请求
                LOG_WARN("无法获取呼叫信息，尝试直接回复请求...");
                if (rdata) {
                    // 直接使用pjsua_reject_incoming_call
                    pjsua_call_hangup(call_id, 488, NULL, NULL);
                }
            }
        } catch (...) {
            LOG_ERROR("拒绝呼叫时出现异常");
        }
    }
}

// 处理SIP呼叫状态
void Application::handleCallState(pjsua_call_id call_id, pjsip_event *e) {
    pjsua_call_info ci;
    pjsua_call_get_info(call_id, &ci);
    
    // 打印呼叫状态
    char state_str[100];
    pj_ansi_snprintf(state_str, sizeof(state_str), "%.*s", (int)ci.state_text.slen, ci.state_text.ptr);
    LOG_INFO("呼叫状态: " + std::string(state_str));
    
    // 检查是否断开连接
    if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
        LOG_INFO("呼叫已断开");
        // 停止推流
        StreamManager::getInstance().stopStreaming();
    }
}

// 处理SIP媒体状态
void Application::handleCallMediaState(pjsua_call_id call_id) {
    LOG_INFO("媒体状态改变，呼叫ID: " + std::to_string(call_id));
}

// 处理SIP请求
pj_bool_t Application::handleRxRequest(pjsip_rx_data *rdata) {
    // 检查是否是MESSAGE请求
    const pj_str_t message_method = pj_str((char*)"MESSAGE");
    if (pj_strcmp(&rdata->msg_info.msg->line.req.method.name, &message_method) == 0) {
        // 提取消息体
        if (rdata->msg_info.msg->body) {
            // 提取消息内容
            std::string message_body((char*)rdata->msg_info.msg->body->data, rdata->msg_info.msg->body->len);
            LOG_INFO("收到MESSAGE消息: " + message_body);
            
            // 处理SIP消息
            handleSipMessage(message_body);
            
            // 回复200 OK
            pjsip_endpt_respond_stateless(pjsua_get_pjsip_endpt(), rdata, 200, NULL, NULL, NULL);
            return PJ_TRUE;
        }
    }
    
    // 返回PJ_FALSE表示未处理，继续传递给其他模块
    return PJ_FALSE;
}

// 处理SIP消息请求
void Application::handleSipMessage(const std::string& message_body) {
    // 提取消息类型
    std::string cmdType = XmlHelper::extractValue(message_body, "CmdType");
    std::string sn = XmlHelper::extractValue(message_body, "SN");
    std::string deviceId = XmlHelper::extractValue(message_body, "DeviceID");
    
    LOG_INFO("命令类型: " + cmdType + ", SN: " + sn + ", 目标设备: " + deviceId);
    
    // 构建目标URI（服务器的URI）
    Config& config = Config::getInstance();
    std::string target_uri = "sip:" + config.SERVER_ID + "@" + config.SERVER_IP + ":" + std::to_string(config.SERVER_PORT);
    LOG_INFO("发送响应到: " + target_uri);
    
    // 根据命令类型生成相应的响应
    std::string response;
    SipManager& sipManager = SipManager::getInstance();
    
    // 处理Catalog请求 - 设备通道列表
    if (cmdType == "Catalog") {
        response = XmlHelper::generateCatalogResponse(sn);
        LOG_INFO("准备发送Catalog响应");
        sipManager.sendMessage(target_uri, response);
    }
    // 处理DeviceStatus请求 - 设备状态
    else if (cmdType == "DeviceStatus") {
        response = XmlHelper::generateDeviceStatusResponse(sn);
        LOG_INFO("准备发送DeviceStatus响应");
        sipManager.sendMessage(target_uri, response);
    }
    // 处理DeviceInfo请求 - 设备信息
    else if (cmdType == "DeviceInfo") {
        response = XmlHelper::generateDeviceInfoResponse(sn);
        LOG_INFO("准备发送DeviceInfo响应");
        sipManager.sendMessage(target_uri, response);
    }
    // 处理PTZ控制请求
    else if (cmdType == "PTZCmd") {
        // 处理PTZ控制，这里只是简单记录，实际应用中需要控制摄像头
        std::string ptzCmd = XmlHelper::extractValue(message_body, "PTZCmd");
        LOG_INFO("收到PTZ控制命令: " + ptzCmd);
        
        // 回复PTZ控制响应
        response = XmlHelper::generatePTZResponse(sn, true);
        sipManager.sendMessage(target_uri, response);
    }
    // 处理录像查询请求
    else if (cmdType == "RecordInfo") {
        LOG_INFO("收到录像查询请求");
        response = XmlHelper::generateRecordInfoResponse(sn);
        sipManager.sendMessage(target_uri, response);
    }
    // 其他命令类型
    else {
        LOG_WARN("收到未处理的命令类型: " + cmdType);
    }
}

// 测试SDP解析
void Application::testSdpParsing() {
    LOG_INFO("执行SDP解析测试");
    
    // 测试用的SDP，基于实际请求中的SDP格式
    std::string test_sdp = 
        "v=0\r\n"
        "o=34020000001320000002 0 0 IN IP4 47.120.9.38\r\n"
        "s=Play\r\n"
        "c=IN IP4 47.120.9.38\r\n"
        "t=0 0\r\n"
        "m=video 30490 TCP/RTP/AVP 96 97 98 99\r\n"
        "a=recvonly\r\n"
        "a=rtpmap:96 PS/90000\r\n"
        "a=rtpmap:98 H264/90000\r\n"
        "a=rtpmap:97 MPEG4/90000\r\n"
        "a=rtpmap:99 H265/90000\r\n"
        "a=setup:passive\r\n"
        "a=connection:new\r\n"
        "y=0105002129\r\n";
    
    // 测试SDP解析
    StreamManager::getInstance().testSdpParsing(test_sdp);
} 